/******************************************************************************
 * Copyright 2007 - 2021 Realtek Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/
 
/* FreeRTOS includes */
//#include <FreeRTOS.h>
//#include <task.h>
//#include <timers.h>
//#include <semphr.h>
#include <autoconf.h>
#include <osdep_service.h>
#include <drv_types.h>
#include <stdio.h>
//#include "netif_intf.h"
//#include "los_task_pri.h"
//#include <realtek.h>
//#include "toppers_service.h"



#include <securec.h>

u8* _harmony_malloc(u32 sz);
void _harmony_mfree(u8 *pbuf, u32 sz);
int rtw_ATOMIC_DEC_AND_TEST(ATOMIC_T *v);
int rltk_get_idx_bydev(struct net_device *dev);


/************skb define************/
struct sk_buff * dev_alloc_skb(unsigned int size)
{
	struct sk_buff *skb=NULL;
    u8 *data=NULL;
	struct skb_data * pdata = NULL;
	//skb = (struct sk_buff *)_rtw_zmalloc(sizeof(struct sk_buff)); // for skb->len, etc.
	skb = (struct sk_buff *)_harmony_malloc(sizeof(struct sk_buff));
	if(!skb)
		goto out;
/*
	_rtw_memset(skb,0,sizeof(struct sk_buff));
	if( 0 == size){
		goto out;
	}
*/	
	//pdata = rtw_malloc(sizeof(struct skb_data)+size);
#ifdef CONFIG_USB_HCI
	pdata = usb_alloc_dma(sizeof(struct skb_data)+size);
#endif
#ifdef CONFIG_SDIO_HCI
	pdata = (struct skb_data *)_harmony_malloc(sizeof(struct skb_data)+size);

#endif
	if(!pdata)
		goto nodata;

	_rtw_memset(skb, 0, sizeof(struct sk_buff));
	
	data = pdata->buf;
	skb->head = (unsigned char*)data;
	skb->data = (unsigned char*)data;
	skb->tail = (unsigned char*)data;
	skb->end = (unsigned char*)data + size;
	skb->len = 0;
	
	skb->zerocp_flag = 0;
	skb->alloc_buf_flag = 1;
#ifdef LITOS_TX_ZERO_COPY
	skb->dma_info = NULL;
#endif
	//printf("%s()-%d: skb=%p, skb->head = %p\n", __FUNCTION__, __LINE__, skb, skb->head);

	OsalAtomicSet(&pdata->ref, 1);
out:
	return skb;
nodata:
	rtw_mfree((u8 *)skb, sizeof(struct sk_buff));
	skb = NULL;
	goto out;
	
}

void dev_kfree_skb_any(struct sk_buff *skb)
{
//	printf("%s()-%d: skb->head = %p\n", __FUNCTION__, __LINE__, skb->head);
//	if(skb->len != 0 && skb->alloc_buf_flag == 1 && skb->head && rtw_ATOMIC_DEC_AND_TEST(&LIST_CONTAINOR(skb->head, struct skb_data, buf)->ref))
	if(skb->alloc_buf_flag == 1 && skb->head && ATOMIC_DEC_AND_TEST(&LIST_CONTAINOR(skb->head, struct skb_data, buf)->ref))
		//rtw_mfree(LIST_CONTAINOR(skb->head, struct skb_data, buf), 0);
	{
	//	printf("%s()-%d: skb->head = %p\n", __FUNCTION__, __LINE__, skb->head);
		#ifdef CONFIG_USB_HCI
			usb_free_dma((char *)LIST_CONTAINOR(skb->head, struct skb_data, buf));
		#endif
		#ifdef CONFIG_SDIO_HCI
			//rtw_mfree(LIST_CONTAINOR(skb->head, struct skb_data, buf), 0);
			_harmony_mfree((u8 *)LIST_CONTAINOR(skb->head, struct skb_data, buf), 0);
		#endif
	}
	//printf("%s()-%d: skb = %p\n", __FUNCTION__, __LINE__, skb);
	if(skb)
	{
		rtw_mfree((u8 *)skb, 0);
	}
}
/**
 *      skb_clone       -       duplicate an sk_buff
 *      @skb: buffer to clone
 *      @gfp_mask: allocation priority
 *
 *      Duplicate an &sk_buff. The new one is not owned by a socket. Both
 *      copies share the same packet data but not structure. The new
 *      buffer has a reference count of 1. If the allocation fails the 
 *      function returns %NULL otherwise the new buffer is returned.
 *      
 *      If this function is called from an interrupt gfp_mask() must be
 *      %GFP_ATOMIC.
 */

#define C(x) clone->x = skb->x

struct sk_buff *skb_clone(const struct sk_buff *skb)
{
	struct sk_buff *clone = NULL;

    u8 *data=NULL;
	struct skb_data * pdata = NULL;

	clone = (struct sk_buff *)_harmony_malloc(sizeof(struct sk_buff));

	if (clone == NULL) {
		RTW_INFO("get clone skbbuf fail,size=%d\n",sizeof(struct sk_buff));
		return NULL;
	}
	memset_s(clone, sizeof(*clone),'\0', sizeof(*clone));
	if(skb->alloc_buf_flag == 1)
		OsalAtomicInc(&LIST_CONTAINOR(skb->head, struct skb_data, buf)->ref);
	
	C(dev);
	C(len);
	C(head);
	C(data);
	C(tail);
	C(end);
#ifdef LITOS_TX_ZERO_COPY
	C(dma_info);
#endif
	C(alloc_buf_flag);
	C(zerocp_flag);
out:
	return clone;
	
}

struct sk_buff *skb_copy(const struct sk_buff *skb)
{
	struct sk_buff *copy;
	
	/*
	 * Allocate the copy buffer
	 */
	copy = dev_alloc_skb(skb->len);

	if (copy == NULL)
		return NULL;
	
	/* Set the tail pointer and length */
	skb_put(copy, skb->len);
	_rtw_memcpy(copy->data, skb->data, skb->len);
	copy->dev = skb->dev;

	return copy;
}

/************netbuf to skb *****************/

struct sk_buff *netBuf2Skb(_nic_hdl ndev, NetBuf *buf)
{
	struct sk_buff *sk_pkt;

	if(buf == NULL)
		return NULL;
	
	sk_pkt = dev_alloc_skb(buf->len+14);

	if(sk_pkt != NULL)
	{
		skb_put(sk_pkt, buf->len);
		_rtw_memcpy(sk_pkt->data, buf->mem+(buf->bufs[1].offset), buf->len);
		sk_pkt->dev = ndev;
	}
	return sk_pkt;
}

NetBuf *skb2netBuf(_nic_hdl ndev, struct sk_buff *skb)
{
	_nic_pkt *buff;
	u32 offset = 0;

	if(skb == NULL) {
		RTW_INFO("skb is NULL");
		return NULL;
	}
	
	if (skb->len == 0 || skb->data == NULL) {
		return NULL;
	}
	
	buff = NetBufDevAlloc(ndev->dev, skb->len);

	if (buff == NULL) {
        return NULL;
    }

	offset = buff->bufs[1].offset;

	if (NetBufGetRoom(buff, 2) < skb->len) {
        RTW_INFO("%s fail, tailroom[%d], len[%d]",
            __func__, NetBufGetRoom(buff, 2), skb->len);
        NetBufFree(buff);
        return NULL;
    }
	if(memcpy_s(buff->mem + offset, skb->len, skb->data, skb->len)!=0)
	{
		NetBufFree(buff);
		return NULL;
    }
		
	NetBufPush(buff, 1, skb->len);	
	return buff;

}



struct net_device *alloc_etherdev(int sizeof_priv)
{
	struct net_device *dev = (struct net_device *) rtw_malloc(sizeof(struct net_device));

	if (dev == NULL) {
		DBG_ERR("allocate net_device failed!");
		return NULL;
	}

	memset(dev,'\0', sizeof(*dev));	
	
	if (sizeof_priv > 0) {
		dev->priv = rtw_malloc(sizeof_priv);

		if (dev->priv == NULL) {
			DBG_ERR("allocate sizeof_priv failed!");
			if(dev)
				rtw_mfree((u8*)dev, sizeof(struct net_device));
			return NULL;
		}
		memset(dev->priv, '\0', sizeof_priv);
	}
	return dev;
}

void free_netdev(struct net_device *dev)
{
	if (dev->priv)
		rtw_mfree(dev->priv, 0);
	if (dev)
		rtw_mfree((u8 *) dev, 0);
}

int dev_alloc_name(struct net_device *net_dev, const char *ifname)
{
	strcpy(net_dev->name, ifname);

	return 0;
}
/********************* os depended utilities ********************/


//----- ------------------------------------------------------------------
// Misc Function
//----- ------------------------------------------------------------------

void save_and_cli(void)
{
	//LOS_IntLock();
}

void restore_flags(void)
{
	//LOS_IntUnLock();
}

void cli(void)
{
	
}

/* Not needed on 64bit architectures */
static unsigned int __div64_32(u64 *n, unsigned int base)
{
	u64 rem = *n;
	u64 b = base;
	u64 res, d = 1;
	unsigned int high = rem >> 32;

	/* Reduce the thing a bit first */
	res = 0;
	if (high >= base) {
		high /= base;
		res = (u64) high << 32;
		rem -= (u64) (high * base) << 32;
	}

	while ((u64)b > 0 && b < rem) {
		b = b+b;
		d = d+d;
	}

	do {
		if (rem >= b) {
			rem -= b;
			res += d;
		}
		b >>= 1;
		d >>= 1;
	} while (d);

	*n = res;
	return rem;
}

/********************* os depended service ********************/

/*
 *  RTL fixed memory pool management
 *
 */
u8* _harmony_malloc(u32 sz)
{
	return OsalMemAlloc(sz);
}

u8* _harmony_zmalloc(u32 sz)
{
	return OsalMemCalloc(sz);	
}

void _harmony_mfree(u8 *pbuf, u32 sz)
{
	OsalMemFree(pbuf);
}

static void _harmony_memcpy(void* dst, const void* src, u32 sz)
{
	memcpy_s(dst, sz, src, sz);
}

static int _harmony_memcmp(void *dst, void *src, u32 sz)
{
	if (!(memcmp(dst, src, sz)))
		return 1;

	return 0;
}

static void _harmony_memset(void *pbuf, int c, u32 sz)
{
	memset_s(pbuf,sz, c, sz);
}

__inline static void _harmony_sema_init(_sema *sema, int init_val)
{
	OsalSemInit(sema, init_val);
}

__inline static void _harmony_sema_free(_sema *sema)
{
	OsalSemDestroy(sema);
}

__inline static void _harmony_sema_up(_sema *sema)
{
	OsalSemPost(sema);
}

__inline static u32 _harmony_sema_down(_sema *sema, u32 timout)
{
	int ret = OsalSemWait(sema,timout);
	if (ret == 0)
		return _SUCCESS;
	else
		return _FAIL;
}

static void _harmony_mutex_init(_mutex *pmutex)
{
	const pthread_mutexattr_t attr = {0,0,1,0};
	int ret;
	ret = OsalMutexInit(pmutex);
}

static void _harmony_mutex_free(_mutex *pmutex)
{
	OsalMutexDestroy(pmutex);
}

static void _harmony_mutex_get(_lock *plock)
{
	OsalMutexLock(plock);
}

static void _harmony_mutex_put(_lock *plock)
{
	OsalMutexUnlock(plock);
}

static void _harmony_enter_critical(_lock *plock, _irqL *pirqL)
{
#if (LOSCFG_KERNEL_SMP ==1)

	OsalSpinLock(plock);
#else
	OsalMutexLock(plock);	

#endif
}

static void _harmony_exit_critical(_lock *plock, _irqL *pirqL)
{
	#if (LOSCFG_KERNEL_SMP ==1)
		OsalSpinUnlock(plock);
#else
		OsalMutexUnlock(plock);
#endif

}

__inline static void _harmony_enter_critical_bh(_lock *plock, _irqL *pirqL)
{
#if (LOSCFG_KERNEL_SMP ==1)

	OsalSpinLock(plock);
#else
	OsalMutexLock(plock);	

#endif
}

__inline static void _harmony_exit_critical_bh(_lock *plock, _irqL *pirqL)
{
#if (LOSCFG_KERNEL_SMP ==1)
	OsalSpinUnlock(plock);
#else
	OsalMutexUnlock(plock);
#endif
}

static int _harmony_enter_critical_mutex(_mutex *pmutex, _irqL *pirqL)
{
	int ret = _SUCCESS;
	if(OsalMutexLock(pmutex)!=0)
		return _FAIL;
	return ret;
}

static void _harmony_exit_critical_mutex(_mutex *pmutex, _irqL *pirqL)
{
	OsalMutexUnlock(pmutex);
}

static void _harmony_spinlock_init(_lock *plock)
{
#if (LOSCFG_KERNEL_SMP ==1)
	OsalSpinInit(plock);
#else
	int ret;
	ret=OsalMutexInit(plock);	
#endif
}

static void _harmony_spinlock_free(_lock *plock)
{
#if (LOSCFG_KERNEL_SMP ==1)
	int ret;
	ret=OsalSpinDestroy(plock);
	//RTW_INFO("%s,ret=%d,plock=%d\n",__func__,ret,plock);
#else
	OsalMutexDestroy(plock);
#endif
}

static void _harmony_spinlock(_lock *plock)
{
#if (LOSCFG_KERNEL_SMP ==1)
	OsalSpinLock(plock);
#else
	OsalMutexLock(plock);	

#endif

}

static void _harmony_spinunlock(_lock *plock)
{
#if (LOSCFG_KERNEL_SMP ==1)
		OsalSpinUnlock(plock);
#else
		OsalMutexUnlock(plock);
#endif

}

static void _harmony_spinlock_irqsave(_lock *plock, _irqL *irqL)
{
	OsalSpinLockIrqSave(plock, *irqL);
}

static void _harmony_spinunlock_irqsave(_lock *plock, _irqL *irqL)
{
	OsalSpinUnlockIrqRestore(plock, *irqL);
}

static int _harmony_init_xqueue( _xqueue* queue, const char* name, u32 message_size, u32 number_of_messages )
{
  
    return 0;
}

static int _harmony_push_to_xqueue( _xqueue* queue, void* message, u32 timeout_ms )
{
    return 0;
}

static int _harmony_pop_from_xqueue( _xqueue* queue, void* message, u32 timeout_ms )
{
    return 0;
}

static int _harmony_deinit_xqueue( _xqueue* queue )
{
    int result = 0;

    return result;
}

static u32 _harmony_get_current_time(void)
{
	return (OsalGetSysTimeMs()* LOSCFG_BASE_CORE_TICK_PER_SECOND / 1000);
}

static u32 _harmony_systime_to_ms(u32 systime)
{
	return systime * 1000 / LOSCFG_BASE_CORE_TICK_PER_SECOND;
}

static u32 _harmony_systime_to_sec(u32 systime)
{
	return 0;
}

static u32 _harmony_ms_to_systime(u32 ms)
{
	return ms * LOSCFG_BASE_CORE_TICK_PER_SECOND / 1000;
}

static u32 _harmony_sec_to_systime(u32 sec)
{
	return 0;
}

#define  mmc_delay_us(us)   OsalUDelay(us)
#define  mmc_delay_ms(ms)   do { \
    uint32_t tick_delay = ((ms)/(1000/LOSCFG_BASE_CORE_TICK_PER_SECOND)); \
    uint32_t rest_delay = (ms)%(1000/LOSCFG_BASE_CORE_TICK_PER_SECOND); \
    if (tick_delay) \
        OsalMSleep(tick_delay *(1000/LOSCFG_BASE_CORE_TICK_PER_SECOND)); \
    if (rest_delay) { \
        mmc_delay_us(rest_delay*1000); \
    } \
}while(0)
	
static void _harmony_msleep_os(int ms)
{
	OsalMSleep((u32)ms);
}

static void _harmony_usleep_os(int us)
{
	OsalMSleep(1);
}

static void _harmony_mdelay_os(int ms)
{
/*#ifdef CONFIG_USB_HCI
	OsalMDelay((u32)ms); 
#endif
#ifdef CONFIG_SDIO_HCI
	mmc_delay_ms((unsigned long)ms);
#endif*/
	OsalMDelay((u32)ms); 
}

static void _harmony_udelay_os(int us)
{
/*#ifdef CONFIG_USB_HCI
	OsalUDelay((u32)us); 
#endif
#ifdef CONFIG_SDIO_HCI
	mmc_delay_us((unsigned long)us);
#endif*/
   OsalUDelay((u32)us); 
}

static void _harmony_yield_os(void)
{
	sched_yield();
}

//----- ------------------------------------------------------------------
// Timer Operation
//----- ------------------------------------------------------------------
//void init_timer(struct timer_list *timer);
//void mod_timer(struct timer_list *timer, u32 delay_time_ms);
//void del_timer_sync(struct timer_list * timer);
//void cancel_timer_ex(struct timer_list * timer);
static void _harmony_init_timer(_timer *ptimer, void *adapter, timer_handler pfunc,void *cntx)
{
	ptimer->create = 0;
	ptimer->function = pfunc;
	ptimer->arg = (unsigned long)cntx;
}

static void _harmony_set_timer(_timer *ptimer, u32 delay_time_ms)
{
#if 1
/*
	u32 uwInterval;
	uwInterval = LOS_MS2Tick(delay_time_ms);
	if (uwInterval == 0)
	{
        DBG_INFO("[INFO] %s: uwInterval [0 -> 1]!\n", __FUNCTION__);
        uwInterval = 1;
	}
	ptimer->expires = uwInterval;

//	if (ptimer->used == 1) {
//		mod_timer(ptimer, uwInterval);
//	} else {
		add_timer(ptimer);
//	}
*/
	
	
	if(ptimer->create == 0)
	{
		ptimer->create = 1;

		OsalTimerCreate(&ptimer->osaltimer,delay_time_ms,ptimer->function, ptimer->arg);
		OsalTimerStartLoop(&ptimer->osaltimer);
	}
	else{
		OsalTimerSetTimeout(&ptimer->osaltimer,delay_time_ms);
	}	
	

#else
    u32 uwInterval;
    u32 uwRet;

    uwInterval = LOS_MS2Tick(delay_time_ms);
    if (uwInterval == 0)
    {
        DBG_ERR("[ERROR] %s: uwInterval = 0!\n", __FUNCTION__);
        return;
    }

    uwRet = LOS_SwTmrCreate(uwInterval, OS_SWTMR_MODE_ONCE, (SWTMR_PROC_FUNC)ptimer->pfnHandler, &(ptimer->usTimerID), &(ptimer->uwArg));
    if (uwRet != LOS_OK)
    {
        DBG_ERR("[ERROR] %s: Timer is not Created!\n", __FUNCTION__);
        return;
    }

    uwRet = LOS_SwTmrStart(ptimer->usTimerID);
    if (uwRet != LOS_OK)
    {
        DBG_ERR("[ERROR] %s: Timer is not Started!\n", __FUNCTION__);
    }	
#endif	
}

static u8 _harmony_cancel_timer(_timer *ptimer,u8 *bcancelled)
{	
	if(ptimer->create == 1)
	{
		if(!(OsalTimerDelete(&ptimer->osaltimer)))
		{
			//RTW_INFO("cancel timer\n");
			ptimer->create = 0;
			*bcancelled = 1;
	
			return 0;
		}
	}
	return 0;
}

static void _harmony_cancel_timer_ex(_timer *ptimer)
{
	OsalTimerDelete(&ptimer->osaltimer);
	ptimer->create = 0;
}

static void _harmony_ATOMIC_SET(ATOMIC_T *v, int i)
{
	OsalAtomicSet(v,i);
}

static int _harmony_ATOMIC_READ(ATOMIC_T *v)
{
	return OsalAtomicRead(v);
}

static void _harmony_ATOMIC_ADD(ATOMIC_T *v, int i)
{
	atomic_add_return(i,v);
}

static void _harmony_ATOMIC_SUB(ATOMIC_T *v, int i)
{
	atomic_add_return(-(i),v);
}
static void _harmony_ATOMIC_INC(ATOMIC_T *v)
{
	OsalAtomicInc(v);
}

static void _harmony_ATOMIC_DEC(ATOMIC_T *v)
{
	OsalAtomicDec(v);
}

static int _harmony_ATOMIC_ADD_RETURN(ATOMIC_T *v, int i)
{
	int temp;

	temp = atomic_add_return(i,v);

	return temp;
}

static int _harmony_ATOMIC_SUB_RETURN(ATOMIC_T *v, int i)
{
	int temp;

	temp = atomic_add_return(-(i),v);

	return temp;
}

static int _harmony_ATOMIC_INC_RETURN(ATOMIC_T *v)
{
	return OsalAtomicIncReturn(v);
}

static int _harmony_ATOMIC_DEC_RETURN(ATOMIC_T *v)
{
	return OsalAtomicDecReturn(v);
}

static u64 _harmony_modular64(u64 n, u64 base)
{
	unsigned int __base = (base);
	unsigned int __rem;

	if (((n) >> 32) == 0) {
		__rem = (unsigned int)(n) % __base;
		(n) = (unsigned int)(n) / __base;
	}
	else
		__rem = __div64_32(&(n), __base);
	
	return __rem;
}

/* Refer to ecos bsd tcpip codes */
static int _harmony_arc4random(void)
{
	u32 res = LOS_TickCountGet();
	static unsigned long seed = 0xDEADB00B;
	seed = ((seed & 0x007F00FF) << 7) ^
	    ((seed & 0x0F80FF00) >> 8) ^ // be sure to stir those low bits
	    (res << 13) ^ (res >> 9);    // using the clock too!
	return (int)seed;
}

static int _harmony_get_random_bytes(void *buf, size_t len)
{
#if 1 //becuase of 4-byte align, we use the follow code style.
	unsigned int ranbuf;
	unsigned int *lp;
	int i, count;
	count = len / sizeof(unsigned int);
	lp = (unsigned int *) buf;

	for(i = 0; i < count; i ++) {
		lp[i] = _harmony_arc4random();  
		len -= sizeof(unsigned int);
	}

	if(len > 0) {
		ranbuf = _harmony_arc4random();
		_harmony_memcpy(&lp[i], &ranbuf, len);
	}
	return 0;
#else
	unsigned long ranbuf, *lp;
	lp = (unsigned long *)buf;
	while (len > 0) {
		ranbuf = _liteos_arc4random();
		*lp++ = ranbuf; //this op need the pointer is 4Byte-align!
		len -= sizeof(ranbuf);
	}
	return 0;
#endif
}

static u32 _harmony_GetFreeHeapSize(void)
{
	return (u32)0;
}

static thread_return _harmony_create_task(_rtw_task_info_s* ptask, const char *name,
	u32  stack_size, u32 priority, thread_func_t func, thread_context *thctx)
{
	u32 uwRet;   
	struct OsalThreadParam initTask;
	(void)memset_s(&initTask,sizeof(initTask), 0, sizeof(initTask ));
	initTask.name = (char *)name;
	initTask.stackSize  = stack_size;
	initTask.priority = priority;
	
	uwRet = OsalThreadCreate(ptask,(OsalThreadEntry)func,thctx);
    if(uwRet != 0){
        RTW_INFO("create the task %s failed!\n",name);
		return _FAIL;
    }
	uwRet =OsalThreadStart(ptask, &initTask);
	if(uwRet != 0){
        RTW_INFO("start the task %s failed!\n",name);
		return _FAIL;
    }
    return _SUCCESS;
}
	
static void _harmony_delete_task(_rtw_task_info_s *ptask)
{
    int status = 0;
	status = OsalThreadDestroy(ptask);
	if(status != 0)
        RTW_INFO("stop the task failed!");
}

void _harmony_wakeup_task(_rtw_task_info_s *ptask)
{
	
}

static void _harmony_thread_enter(char *name)
{
	RTW_INFO("\n\rRTKTHREAD %s\n", name);
}

static void _harmony_thread_exit(void)
{
	//DBG_INFO("\n\rRTKTHREAD exit %s\n", __FUNCTION__); 
}
#ifdef USE_RTW_SKB_DEFINE
struct sk_buff *_harmony_skb_alloc(u32 sz)
{
	return dev_alloc_skb(sz);
}
void _harmony_skb_free(const struct sk_buff *skb)
{
	dev_kfree_skb_any(skb);
}
struct sk_buff *_harmony_skb_copy(const  struct sk_buff *skb)
{
	return skb_copy(skb);
}
struct sk_buff *_harmony_skb_clone(const  struct sk_buff *skb)
{
	return skb_clone(skb);
}


int _harmony_netif_rx(_nic_hdl ndev, struct sk_buff *skb)
{
	int idx=0,i;
	_nic_pkt *buff;
	u32 offset = 0;
	int ret;

	buff = skb2netBuf(ndev, skb);
	if(buff == NULL)
		return 0;
	
#if 1
	/*if( *(skb->data+34) == 0x08 && *(skb->data+35) == 0x00  || *(skb->data+36) == 0x08 && *(skb->data+37) == 0x00){
		printf("*(skb->data+34) == 0x08 && *(skb->data+35) == 0x00 \n");
		for(i=0;i<skb->len-8;i+=8)
			printf("%02X%02X %02X%02X %02X%02X %02X%02X\n",*(skb->data+i),*(skb->data+i+1),*(skb->data+i+2),*(skb->data+i+3),*(skb->data+i+4),*(skb->data+i+5),*(skb->data+i+6),*(skb->data+i+7));
		while(i<skb->len)
		{	printf("%02X",*(skb->data+i));i++;}
	}
	if( *(skb->data+36) == 0x08 && *(skb->data+37) == 0x00){
		printf("*(skb->data+36) == 0x08 && *(skb->data+37) == 0x00 \n");
		for(i=0;i<skb->len-8;i+=8)
			printf("%02X%02X %02X%02X %02X%02X %02X%02X\n",*(skb->data+i),*(skb->data+i+1),*(skb->data+i+2),*(skb->data+i+3),*(skb->data+i+4),*(skb->data+i+5),*(skb->data+i+6),*(skb->data+i+7));
		while(i<skb->len)
		{	printf("%02X",*(skb->data+i));i++;}
	}
	if( *(skb->data+12) == 0x08 && *(skb->data+13) == 0x00){ 
		printf("_harmony_netif_rx:*(skb->data+12) == 0x08 && *(skb->data+13) == 0x00 \n");
		for(i=0;i<skb->len-8;i+=8)
			printf("%02X%02X %02X%02X %02X%02X %02X%02X\n",*(skb->data+i),*(skb->data+i+1),*(skb->data+i+2),*(skb->data+i+3),*(skb->data+i+4),*(skb->data+i+5),*(skb->data+i+6),*(skb->data+i+7));
		while(i<skb->len)
		{	printf("%02X",*(skb->data+i));i++;}
		printf("\n");
	}*/
	
	if((*(skb->data+12) == 0x08 && *(skb->data+13) == 0x00)&&!1){ //just for ip data
		//printf("unvalid IP\n\r");
		goto exit;
	}
#endif	
	ret=NetIfRxNi(ndev->dev,buff);
	if(ret!=0)
	{
		NetBufFree(buff);
		return 0;
	}
exit:
	dev_kfree_skb_any(skb);
	return 1;
}

#endif
const struct osdep_service_ops osdep_service = {
	_harmony_malloc,		    //rtw_vmalloc
	_harmony_zmalloc,		//rtw_zvmalloc
	_harmony_mfree,			//rtw_vmfree
	_harmony_malloc,         //rtw_malloc
	_harmony_zmalloc,        //rtw_zmalloc
	_harmony_mfree,          //rtw_mfree
	_harmony_memcpy,         //rtw_memcpy
	_harmony_memcmp,         //rtw_memcmp
	_harmony_memset,          //rtw_memset
	_harmony_sema_init, //rtw_init_sema
	_harmony_sema_free, //rtw_free_sema
	_harmony_sema_up, //rtw_up_sema
	_harmony_sema_down, //rtw_down_sema
	_harmony_mutex_init, //rtw_mutex_init
	_harmony_mutex_free, //rtw_mutex_free
	_harmony_mutex_get, //rtw_mutex_get
	_harmony_mutex_put, //rtw_mutex_put
	_harmony_enter_critical,		//rtw_enter_critical
	_harmony_exit_critical,		//rtw_exit_critical
	_harmony_enter_critical_bh,		//rtw_enter_critical_bh
	_harmony_exit_critical_bh,		//rtw_exit_critical_bh
	_harmony_enter_critical_mutex,		//rtw_enter_critical_mutex
	_harmony_exit_critical_mutex,		//rtw_exit_critical_mutex
	_harmony_spinlock_init, //rtw_spinlock_init
	_harmony_spinlock_free, //rtw_spinlock_free
	_harmony_spinlock, //rtw_spin_lock
	_harmony_spinunlock, //rtw_spin_unlock
	_harmony_spinlock_irqsave,	//rtw_spinlock_irqsave
	_harmony_spinunlock_irqsave,//rtw_spinunlock_irqsave
	NULL,//rtw_init_xqueue
	NULL,//rtw_push_to_xqueue
	NULL,//rtw_pop_from_xqueue
	NULL,//rtw_deinit_xqueue
	_harmony_get_current_time, //rtw_get_current_time
	_harmony_systime_to_ms, //rtw_systime_to_ms
	_harmony_systime_to_sec, //rtw_systime_to_sec
	_harmony_ms_to_systime, //rtw_ms_to_systime
	_harmony_sec_to_systime, //rtw_sec_to_systime
	_harmony_msleep_os, //rtw_msleep_os
	_harmony_usleep_os, //rtw_usleep_os
	_harmony_mdelay_os, //rtw_mdelay_os
	_harmony_udelay_os, //rtw_udelay_os
	_harmony_yield_os, //rtw_yield_os
	
	_harmony_init_timer, //rtw_init_timer
	_harmony_set_timer, //rtw_set_timer
	_harmony_cancel_timer, //rtw_cancel_timer
	_harmony_cancel_timer_ex, //rtw_del_timer
	
	_harmony_ATOMIC_SET, //ATOMIC_SET
	_harmony_ATOMIC_READ, //ATOMIC_READ
	_harmony_ATOMIC_ADD, //ATOMIC_ADD
	_harmony_ATOMIC_SUB, //ATOMIC_SUB
	_harmony_ATOMIC_INC, //ATOMIC_INC
	_harmony_ATOMIC_DEC, //ATOMIC_DEC
	_harmony_ATOMIC_ADD_RETURN, //ATOMIC_ADD_RETURN
	_harmony_ATOMIC_SUB_RETURN, //ATOMIC_SUB_RETURN
	_harmony_ATOMIC_INC_RETURN, //ATOMIC_INC_RETURN
	_harmony_ATOMIC_DEC_RETURN, //ATOMIC_DEC_RETURN
	
	_harmony_modular64, //rtw_modular64
	_harmony_get_random_bytes,			//rtw_get_random_bytes
	_harmony_GetFreeHeapSize,		//rtw_getFreeHeapSize
	
	_harmony_create_task,		//rtw_create_task
	_harmony_delete_task,		//rtw_delete_task
	_harmony_wakeup_task,		//rtw_wakeup_task

	_harmony_thread_enter,		//rtw_thread_enter
	_harmony_thread_exit,		//rtw_thread_exit
#ifdef USE_RTW_SKB_DEFINE
	_harmony_skb_alloc,
	_harmony_skb_free,
	_harmony_skb_copy,
	_harmony_skb_clone,
	_harmony_netif_rx
#endif
};

